﻿using System;
using System.IO;
using System.Diagnostics;
using TimeSnapperPluginAPI;

namespace CSharpSamplePlugin
{
    public class LogEveryPossibleThing : ITimeSnapperPlugin
    {
        #region ITimeSnapperPlugin Members

        bool ITimeSnapperPlugin.Configurable
        {
            get
            {
                Logger.Log("Configurable.get was called");
                return true;
            }
        }

        void ITimeSnapperPlugin.Configure()
        {
            Logger.Log("Configure() was called");
            return;
        }

        string ITimeSnapperPlugin.Description
        {
            get
            {
                Logger.Log("Description.get was called");
                return "A sample plugin that logs every detail of every TimeSnapper event.\r\n\r\nIt is intended to show how to access all of TimeSnapper's events.\r\n\r\nIt is, however, **NOT** a best practice example of logging, and may thus slow down TimeSnapper's performance as the log file gets larger.\r\n\r\nPlease don't leave this sample running all the time.";
            }
        }

        string ITimeSnapperPlugin.FriendlyName
        {
            get { return "Log The Lot"; }
        }

        object ITimeSnapperPlugin.HandleEvent(TimeSnapperEvent timeSnapperEvent, IServices services, EventArgs args)
        {
            Logger.Log(timeSnapperEvent.ToString());
            switch (timeSnapperEvent)
            {
                case TimeSnapperEvent.Archived:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.ArchivedEventArgs)args;
                        Logger.Log("specificArgs.AllowedAge =" + specificArgs.AllowedAge.ToString());
                    }
                    break;
                case TimeSnapperEvent.ArchivingCancel:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.ArchivingCancelEventArgs)args;
                        //specificArgs.Cancel = true;  
                        //^^^ this would cancel the archiving.
                        Logger.Log("specificArgs.AllowedAge =" + specificArgs.AllowedAge.ToString());

                    }
                    break;
                case TimeSnapperEvent.AutoPoppingUpCancel:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.AutoPoppingUpCancelEventArgs)args;
                        //specificArgs.Cancel = true; 
                        //^^^ this would cancel the popup.
                    }
                    break;
                case TimeSnapperEvent.Closing:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.ClosingCancelEventArgs)args;
                        //specificArgs.Cancel = true; 
                        //^^^ this would cancel the closing of the application.
                        //   (Unless the application is being closed due to 
                        //   a system wide shutdown. In which case, TimeSnapper 
                        //   will shutdown regardless of what plugins say.)
                    }
                    break;
                case TimeSnapperEvent.FlagSaved:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.FlagSavedEventArgs)args;
                        Flag flag = specificArgs.Flag;
                        Logger.Log(flag);
                    }
                    break;
                case TimeSnapperEvent.FlagSavingCancel:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.FlagSavingCancelEventArgs)args;
                        //specificArgs.Cancel = true; 
                        //^^^ this would cancel the saving of the flag
                        Flag flag = specificArgs.Flag;
                        Logger.Log(flag);
                    }
                    break;
                case TimeSnapperEvent.PluginsLoaded:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.PluginsLoadedEventArgs)args;
                        var plugins = specificArgs.Plugins;
                        Logger.Log(plugins);                        
                    }
                    break;
                case TimeSnapperEvent.SnapshotDeleted:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.SnapshotDeletedEventArgs)args;                       
                        Logger.Log("Deleted: '" + specificArgs.Filename + "'");
                    }
                    break;
                case TimeSnapperEvent.SnapshotDeletingCancel:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.SnapshotDeletingCancelEventArgs)args;
                        //specificArgs.Cancel = true; 
                        //^^^ this would cancel the deleting of the snapshot
                        Logger.Log("About to delete: '" + specificArgs.Filename + "'");
                    }
                    break;
                case TimeSnapperEvent.SnapshotSaved:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.SnapshotSavedEventArgs)args;
                        Logger.Log(specificArgs.Activity);                        
                    }
                    break;
                case TimeSnapperEvent.SnapshotTakenSavingCancel:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.SnapshotTakenSavingCancelEventArgs)args;
                        //specificArgs.Cancel = true; 
                        //^^^ this would cancel the saving of the snapshot       
                        Logger.Log(specificArgs.SnapshotInfo);                        
                    }
                    break;
                case TimeSnapperEvent.SnapshotTakingCancel:
                    {
                        var specificArgs = (TimeSnapperPluginAPI.SnapshotTakingCancelEventArgs)args;
                        //specificArgs.Cancel = true; 
                        //^^^ this would cancel the taking of the snapshot
                        Logger.Log(specificArgs.Activity);                        
                    }
                    break;
                default:
                    //What happened!?
                    break;
            }
            return null;
        }

        TimeSnapperMenuItem[] ITimeSnapperPlugin.MenuItems()
        {
            return null;
        }

        Guid ITimeSnapperPlugin.PluginID
        {
            get { return new Guid("727F50D3-5BAC-4990-904B-A68E32E5AEFD"); }
        }

        TimeSnapperEvent[] ITimeSnapperPlugin.SubscribesTo()
        {
            //Let's subscribe to everything so we can log every event.
            TimeSnapperEvent[] subscribesTo = { TimeSnapperEvent.Archived, 
                                 TimeSnapperEvent.ArchivingCancel ,
                                 TimeSnapperEvent.AutoPoppingUpCancel ,
                                 TimeSnapperEvent.Closing,
                                 TimeSnapperEvent.FlagSaved ,
                                 TimeSnapperEvent.FlagSavingCancel ,
                                 TimeSnapperEvent.PluginsLoaded ,
                                 TimeSnapperEvent.SnapshotDeleted ,
                                 TimeSnapperEvent.SnapshotDeletingCancel ,
                                 TimeSnapperEvent.SnapshotSaved ,
                                 TimeSnapperEvent.SnapshotTakenSavingCancel  ,
                                 TimeSnapperEvent.SnapshotTakingCancel };                           
            return  subscribesTo;
        }

        #endregion
    }

    public static class Logger
    {
        private static bool logWritingFailed = false;
        private static string LogFilename = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "TimeSnapper\\LogTheLot" + DateTime.Now.ToString("yyyyMMdd") + ".txt");
        public static void Log(string message)
        {
            Debug.WriteLine(message);
            
            message = message.Replace("\r\n", "\t\r\n");

            StreamWriter sw = null;

            //we've had a previous problem with logging? don't try again.
            if (logWritingFailed) return;

            //note i'm using 'try/finally' rather than 'using' since i want more explicit control of exception handling
            //...i still recommend you start off with:  "using (var sw = File.AppendText(LogFileName) { ... } "
            //...and only break it out into a full try/finally if you really need to.

            //and also... it's a pretty poor way to act: re-opening the file each time we want to log one line...
            //but this sample is about examining all the things TimeSnapper sends us...
            //definitely not a best practice logging sample... horribly inefficent in that regard.
            //
            //For that reason, I don't recommend you leave this plugin in use permanently.

            try
            {
                sw = File.AppendText(LogFilename);
                sw.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + message);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                logWritingFailed  = true;
            }
            finally
            {

                try
                {
                    //'This will throw an exception if we're out of space. 
                    if (sw != null) sw.Close();
                }
                catch (IOException iex)
                {
                    Debug.WriteLine(iex);
                    logWritingFailed  = true;
                }

            }
        }
    
        internal static void Log(Flag flag)
        {
            Logger.Log("\tflag.Color = " + flag.Color.ToString());
            Logger.Log("\tflag.Comment = " + flag.Comment);
            Logger.Log("\tflag.FlagDate = " + flag.FlagDate.ToString());
            Logger.Log("\tflag.FlagId = " + flag.FlagId);
            Logger.Log("\tflag.FlagType = " + flag.FlagType.ToString());
            Logger.Log("\tflag.Text1 = " + flag.Text1);
            Logger.Log("\tflag.Text2 = " + flag.Text2);
            Logger.Log("\tflag.Text3 = " + flag.Text3);
            Logger.Log("\tflag.Text4 = " + flag.Text4);
            Logger.Log("\tflag.Text5 = " + flag.Text5);
            Logger.Log("\tflag.Text6 = " + flag.Text6);
        }

        internal static void Log(ITimeSnapperPlugin[] plugins)
        {
            if (plugins != null)
            {
                foreach (var p in plugins)
                {
                    Logger.Log(p);
                }
            }
        }

        internal static void Log(ITimeSnapperPlugin p)
        {
            Logger.Log("\tPlugin.FriendlyName = '" + p.FriendlyName + "'");
            Logger.Log("\tPlugin.Description = '" + p.Description + "'");
            Logger.Log("\tPlugin.Configurable = " + p.Configurable.ToString());
            Logger.Log("\tPlugin.SubscribesTo = ");
            Logger.Log(p.SubscribesTo());
        }

        private static void Log(TimeSnapperEvent[] timeSnapperEvents)
        {
            if (timeSnapperEvents != null)
            {
                foreach (var e in timeSnapperEvents)
                {
                    Logger.Log("\t\t" + e.ToString());
                }
            }
        }

        internal static void Log(Activity activity)
        {
            Logger.Log("\tactivity.ActivityId: " + activity.ActivityId);
            Logger.Log("\tactivity.Crc32: " + activity.Crc32);
            Logger.Log("\tactivity.Domain: " + activity.Domain);
            Logger.Log("\tactivity.Duration: " + activity.Duration);
            Logger.Log("\tactivity.Filename: " + activity.Filename);
            Logger.Log("\tactivity.FileSize: " + activity.FileSize);
            Logger.Log("\tactivity.Program: " + activity.Program);
            Logger.Log("\tactivity.ProgramCaption: " + activity.ProgramCaption);
            Logger.Log("\tactivity.ProgramPath: " + activity.ProgramPath);
            Logger.Log("\tactivity.PwdId: " + activity.PwdId);
            Logger.Log("\tactivity.SnapDate: " + activity.SnapDate);
            Logger.Log("\tactivity.Url: " + activity.Url);
            
        }

        internal static void Log(SnapshotInfo snapshotInfo)
        {
            Logger.Log("\tsnapshotInfo.Crc32: " + snapshotInfo.Crc32);
            Logger.Log("\tsnapshotInfo.Destination: " + snapshotInfo.Destination);
            Logger.Log("\tsnapshotInfo.Format: " + snapshotInfo.Format);
            Logger.Log("\t" +snapshotInfo.Image);
            Logger.Log("\tsnapshotInfo.Quality: " + snapshotInfo.Quality);
            
        }

        private static void Log(System.Drawing.Bitmap bitmap)
        {
            Logger.Log("\tbitmap.Height: " + bitmap.Height);
            Logger.Log("\tbitmap.HorizontalResolution: " + bitmap.HorizontalResolution);
            Logger.Log("\tbitmap.PixelFormat: " + bitmap.PixelFormat.ToString());
            Logger.Log("\tbitmap.RawFormat: " + bitmap.RawFormat.ToString());
            Logger.Log("\tbitmap.VerticalResolution: " + bitmap.VerticalResolution);            
            Logger.Log("\tbitmap.Width: " + bitmap.Width);
        }
    }
}
